/*
 * 创建日期 2005-10-29
 *
 * 更改所生成文件模板为
 * 窗口 > 首选项 > Java > 代码生成 > 代码和注释
 */
package com.vanda.report.dp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.vanda.report.ReportException;
import com.vanda.report.ReportGroupRow;
import com.vanda.report.ReportInnerData;
import com.vanda.report.Validation;
import com.vanda.report.element.Element;
/**
 * 分组标签，类似于sql的group by，必须附属于<function>标签 <br>
 * <p>
 * 
 * @author eagle <br>
 * @version Version 1.00 <br>
 */
public class GroupElement extends Element {
	/** 分组列名称，如有多列，以","作为分隔符 */
	private String field = null;

	public void validator() throws ReportException {
		Validation.checkRequired("GroupElement", "field", field);
	}

	private String[] groupFields = null;
	private Object[] oldDatas = null; //用于比较的字段（上一行）
	private boolean first = true;
	private int start = 0;
	private int end = 0;
	
	/** 指定新行的名称 */
	private String name = null;

	/**
	 * 标签执行方法，递归执行
	 * 临时变量说明:
	 * temp1:原始数据list
	 * temp2:当前行数
	 * temp4:保存每个gourp的起始结束位置,int[2]
	 * @param obj
	 */
	public void execute(Object obj) throws ReportException {
		try {
			ReportInnerData reportData = (ReportInnerData) obj;
			Object contextObj = reportData.getContextData();

			//取临时数据
			List objList = (List) reportData.getTemp1();
			int index = ((Integer) reportData.getTemp2()).intValue();
			//最先处理的行（最后一行），为group的首行
			if (index == objList.size() - 1)
				first = true;

			//如果是group结果，直接跳过
			if (contextObj instanceof ReportGroupRow)
				return;

			Object[] indexObjs = (Object[]) reportData.getTemp3();
			int[] pos = new int[2];
			reportData.setTemp4(null);

			//用于比较的字段（当前行）
			Object[] currentDatas = getGroupData(contextObj, groupFields);

			//如果是第一次,不做新旧数据判断
			if (first) {
				oldDatas = currentDatas;
				first = false;
				end = index + 1;
			}

			boolean bCreateRecord = isCreateRecord();

			//如果不相等
			if (!equalsGroupData(currentDatas, oldDatas)) {
				pos[0] = index + 1;
				pos[1] = end;
				reportData.setTemp4(pos);

				//如果有新增行
				if (bCreateRecord) {

					ReportGroupRow newRecord = this.getNewGroupRow(oldDatas);

					putNewRecord(
						end,
						newRecord,
						(List) indexObjs[0],
						(HashMap) indexObjs[1]);
					reportData.setContextData(newRecord);
				}

				super.execute(obj);

				end = index + 1;
				start = index;
			}

			//如果是最后一行(除掉ReportGroupRow)
			if (isLastRow(objList, index) == true) {
				pos[0] = index;
				pos[1] = end;
				reportData.setTemp4(pos);
				//如果有新增行
				if (bCreateRecord) {

					ReportGroupRow newRecord = this.getNewGroupRow(currentDatas);

					putNewRecord(
						end,
						newRecord,
						(List) indexObjs[0],
						(HashMap) indexObjs[1]);
					reportData.setContextData(newRecord);
				}

				super.execute(obj);
			}

			//保存当前值
			oldDatas = currentDatas;
			reportData.setTemp4(null);
		} catch (ReportException e) {
			throw e;
		} catch (Exception e) {
			throw new ReportException(e);
		}

	}

	private ReportGroupRow getNewGroupRow(Object[] groupDatas) throws Exception{
		ReportGroupRow newRecord = new ReportGroupRow();
		newRecord.setName(name);
		
		for(int i=0;i<groupFields.length;i++){
			super.setProperty(newRecord, groupFields[i], groupDatas[i]);
		}
		
		return newRecord;
	}
	
	/**
	 * 判断是否是最后一行(不包括ReportGroupRow)
	 * @param objList
	 * @param index
	 * @return
	 */
	private boolean isLastRow(List objList, int index) {
		if (index == 0) {
			return true;
		}
		//如果index之前的记录都是ReportGroupRow的话,那么此行为最后一行
		for (int i = 0; i < index; i++) {
			Object temp = objList.get(i);

			if (!(temp instanceof ReportGroupRow)) {
				return false;
			}
		}

		return true;
	}

	private void putNewRecord(
		int index,
		Object newRecord,
		List lstIndex,
		HashMap map) {
		Integer key = new Integer(index);
		List lst = (List) map.get(key);
		if (lst == null) {
			lst = new ArrayList();
			lstIndex.add(key);
			map.put(key, lst);
		}

		lst.add(newRecord);

	}

	/**
	 * 检查是否需要新加行
	 * @return
	 */
	private boolean isCreateRecord() {
		List listSub = super.getSubElements();
		for (int i = 0; i < listSub.size(); i++) {
			AggregationElement sub = (AggregationElement) listSub.get(i);
			if (sub.isCreateRecord() == true) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 取得group数据
	 * @param temp
	 * @param groupFields
	 * @return
	 */
	private Object[] getGroupData(Object temp, String[] groupFields)
		throws ReportException {
		Object[] data = new Object[groupFields.length];

		for (int i = 0; i < groupFields.length; i++) {
			try {
				data[i] = super.getProperty(temp, groupFields[i]);
			} catch (ReportException e) {
				throw e;
			} catch (Exception e) {
				throw new ReportException(
					"field[" + groupFields[i] + "] is not exist!",
					e);
			}
		}
		return data;
	}

	/**
	 * 判断是否相等
	 * @param currentData
	 * @param oldData
	 * @return
	 */
	private boolean equalsGroupData(Object[] currentData, Object[] oldData) {
		if (oldData == null) {
			return false;
		}
		for (int i = 0; i < currentData.length; i++) {
			if (currentData[i] == null && oldData[i] == null) {
				continue;
			}
			if (currentData[i] == null || oldData[i] == null) {
				return false;
			}
			if (!currentData[i].equals(oldData[i])) {
				return false;
			}
		}
		return true;
	}

	/**
	 * @return
	 */
	public String getField() {
		return field;
	}

	/**
	 * @param string
	 */
	public void setField(String string) {
		field = string;
		groupFields = field.split(",");
		for (int i = 0; i < groupFields.length; i++) {
			groupFields[i] = groupFields[i].trim();
		}
	}

	/**
	 * @return
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param string
	 */
	public void setName(String string) {
		name = string;
	}

}
